package com.graphcoloring;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.sat4j.specs.TimeoutException;

public class PerformanceTester {
	private static String[] instances;
		
	private List<Solver> solvers;
	private List<GraphInputData> dataList;
		
	public PerformanceTester(List<Solver> solvers) throws IOException {
		this(solvers, loadTestData());
	}
	
	private static void readInstances() throws IOException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("instances.dat")));
		
		String s;
		
		List<String> ins = new ArrayList<String>();
		while ((s = reader.readLine()) != null) {
			ins.add(s);
		}
		instances = ins.toArray(new String[ins.size()]);
		reader.close();
	}
	
	private static List<GraphInputData> loadTestData() throws IOException {
		List<GraphInputData> dataList = new ArrayList<GraphInputData>();
		
		File file = new File("data");
		for (String testData : file.list()) {
			GraphInputData data = new GraphInputData("data/" + testData);
			dataList.add(data);
		}
		
		return dataList;
	}

	public PerformanceTester(List<Solver> solvers, List<GraphInputData> data) {
		this.solvers = solvers;
		this.dataList = data;
	}
	
	
	public PerformanceResult performTest() throws Exception {
		long[][] executionTime = new long[dataList.size()][solvers.size()];
		long[][] colorCount = new long[dataList.size()][solvers.size()];
		
		int i = 0;
		for (GraphInputData data : dataList) {
			System.out.println(instances[i] + " ");
			
			int j = 0;
			for (Solver solver : solvers) {
				long startTime = 0,endTime = 0;
				Solution solution = null;
				
				boolean timeout = false;
				try {
					startTime = System.currentTimeMillis();
					solution = solver.solve(data);
					endTime = System.currentTimeMillis();					
				} catch(TimeoutException exp) {
					timeout = true;
				} catch (OutOfMemoryError exp) {
					timeout = true;
					System.gc();
					System.runFinalization();
				}
				
				if (!timeout) {
					long time = (endTime - startTime) / 1000;
					executionTime[i][j] = time;
					colorCount[i][j] = solution.colorCount;
				}
				else
					executionTime[i][j] = -1;
		
				System.out.print(solver.getClass().getSimpleName() + " ");
				System.out.print("colors: " + colorCount[i][j] + " ");
				System.out.print("time: " + executionTime[i][j] + " ");
				
				System.out.print("coloring: ");
				for (int q = 0; q < data.getVertexNumber(); q++)
					System.out.print(solution.colors[q] + " ");
				System.out.println();
				
				System.out.flush();
				j++;
			}
			i++;
			
			System.out.println();
		}
		PerformanceResult result = new PerformanceResult();
		result.executionTime = executionTime;
		result.colorCount = colorCount;
		return result;
	}
	
	public static void main(String[] args) throws Exception {
		readInstances();
		
		List<Solver> solvers = new ArrayList<Solver>();
//		solvers.add(new BruteForceSolver());
		solvers.add(new NaiveEncodingSolverMoreClauses());
		solvers.add(new NaiveBCESolver());
//		solvers.add(new NaiveEncodingSolver());
//		solvers.add(new StandardBitwiseSolver());
//		solvers.add(new ExplicitBitwiseSolver());
//		solvers.add(new OrderEncodingSolver());
//		solvers.add(new ChenAMOSolver());
		
		List<GraphInputData> dataList = new ArrayList<GraphInputData>();		
		
		for (String instance : instances)
			dataList.add(new GraphInputData("data/" + instance));
		
		PerformanceTester tester = new PerformanceTester(solvers,dataList);
		tester.performTest();		
	}
}
